{% from "header.jinja" import header %}

"""{{ header() }}"""

import importlib
from weakref import WeakKeyDictionary, ref
from typing import TYPE_CHECKING, Any, Dict, Literal, overload

from . import VERSIONS, LATEST_VERSION, VERSION_TYPE

if TYPE_CHECKING:
    from githubkit import GitHubCore
    {% for version, module in versions.items() %}
    from .{{ module }}.rest import RestNamespace as {{ pascal_case(module) }}RestNamespace
    {% endfor %}

if TYPE_CHECKING:

    class _VersionProxy({{ pascal_case(versions[latest_version]) }}RestNamespace):
        ...

else:
    _VersionProxy = object

class RestVersionSwitcher(_VersionProxy):
    _cached_namespaces: "WeakKeyDictionary[GitHubCore, Dict[VERSION_TYPE, Any]]" = WeakKeyDictionary()

    if not TYPE_CHECKING:
        def __getattr__(self, name: str) -> Any:
            if name.startswith("_"):
                raise AttributeError(
                    f"'{self.__class__.__name__}' object has no attribute '{name}'"
                )
            namespace = self()
            return getattr(namespace, name)

    def __init__(self, github: "GitHubCore"):
        self._github_ref = ref(github)

    @property
    def _github(self) -> "GitHubCore":
        if g := self._github_ref():
            return g
        raise RuntimeError(
            "GitHub client has already been collected. "
            "Do not use the namespace after the client has been collected."
        )

    {% for version, module in versions.items() %}
    @overload
    def __call__(self, version: Literal["{{ version }}"]) -> "{{ pascal_case(module) }}RestNamespace":
        ...
    {% endfor %}

    @overload
    def __call__(self) -> "{{ pascal_case(versions[latest_version]) }}RestNamespace":
        ...

    def __call__(self, version: VERSION_TYPE = LATEST_VERSION) -> Any:
        g = self._github
        cache = self._cached_namespaces.setdefault(g, {})
        if version in cache:
            return cache[version]
        module = importlib.import_module(f".{VERSIONS[version]}.rest", __package__)
        namespace = module.RestNamespace(g)
        cache[version] = namespace
        return namespace
